package com.property.demo.service.impl;

import com.property.demo.model.Building;
import com.property.demo.model.Community;
import com.property.demo.repository.BuildingRepository;
import com.property.demo.repository.CommunityRepository;
import com.property.demo.service.BuildingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;

@Service
public class BuildingServiceImpl implements BuildingService {

    @Autowired
    private BuildingRepository buildingRepository;
    
    @Autowired
    private CommunityRepository communityRepository;

    @Override
    public List<Building> findAll() {
        return buildingRepository.findAll();
    }

    @Override
    public Page<Building> findAll(Pageable pageable) {
        return buildingRepository.findAll(pageable);
    }

    @Override
    public Page<Building> findByFilters(Long communityId, String name, Pageable pageable) {
        Specification<Building> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            if (communityId != null) {
                predicates.add(criteriaBuilder.equal(root.get("community").get("id"), communityId));
            }
            
            if (name != null && !name.isEmpty()) {
                predicates.add(criteriaBuilder.like(criteriaBuilder.lower(root.get("name")), "%" + name.toLowerCase() + "%"));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        return buildingRepository.findAll(spec, pageable);
    }

    @Override
    public Building findById(Long id) {
        return buildingRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("Building not found with id: " + id));
    }

    @Override
    public Building save(Building building) {
        // Verify community exists
        Community community = communityRepository.findById(building.getCommunity().getId())
                .orElseThrow(() -> new EntityNotFoundException("Community not found with id: " + building.getCommunity().getId()));
        
        building.setCommunity(community);
        return buildingRepository.save(building);
    }

    @Override
    public Building update(Long id, Building buildingDetails) {
        Building building = findById(id);
        
        building.setName(buildingDetails.getName());
        
        // Only update community if it's provided
        if (buildingDetails.getCommunity() != null && buildingDetails.getCommunity().getId() != null) {
            Community community = communityRepository.findById(buildingDetails.getCommunity().getId())
                    .orElseThrow(() -> new EntityNotFoundException("Community not found with id: " + buildingDetails.getCommunity().getId()));
            building.setCommunity(community);
        }
        
        building.setTotalFloors(buildingDetails.getTotalFloors());
        building.setTotalUnits(buildingDetails.getTotalUnits());
        building.setDescription(buildingDetails.getDescription());
        
        return buildingRepository.save(building);
    }

    @Override
    public void delete(Long id) {
        Building building = findById(id);
        buildingRepository.delete(building);
    }

    @Override
    public List<Building> findByCommunityId(Long communityId) {
        // Verify community exists
        communityRepository.findById(communityId)
                .orElseThrow(() -> new EntityNotFoundException("Community not found with id: " + communityId));
                
        return buildingRepository.findByCommunityId(communityId);
    }

    @Override
    public List<Building> findByNameContainingAndCommunityId(String name, Long communityId) {
        // Verify community exists
        communityRepository.findById(communityId)
                .orElseThrow(() -> new EntityNotFoundException("Community not found with id: " + communityId));
                
        return buildingRepository.findByNameContainingAndCommunityId(name, communityId);
    }
} 